#include "Socket.hpp"
#include "log.hpp"
#include "Epoll.hpp"
#include <functional>
#include <unordered_map>
#include <cassert>
using namespace std;

class TcpSever;
class Conncet;
typedef function<void(Conncet *)> func_t;
//typedef function<void(Conncet* conn,string& requst)> _callback_t;
class Conncet
{
public:
    // 构造函数一会再说吧
    Conncet(int sock, TcpSever *tsvr)
        : _sock(sock), _tsvr(tsvr)
    {
    }

public:
    // 对应套接字得有
    int _sock;
    // 对应的读、写、异常方法
    func_t _recv_cb;
    func_t _send_cb;
    func_t _except_cb;

    // 对于每个sock来说 都需要专属自己的读写缓冲区
    string _inbuffer;
    string _outbuffer;

    // 这个回指指针目前来说反正挺莫名其妙的
    TcpSever *_tsvr;
};

class TcpSever
{
    const static int g_revs_num = 128;

public:
    TcpSever(uint16_t port = 8000)
        : _port(port), _revs_num(g_revs_num)
    {
        // 第一步部要创建epoll模型
        _epoll.Epoll_create();
        // 第二步创建listen套接字
        _listensocket = Sock::Socket();
        Sock::Bind(_listensocket, _port);
        Sock::Listen(_listensocket);

        // 都创建好了之后,将listen套接字添加到epoll中
        AddConnection(_listensocket, std::bind(&TcpSever::Accepter, this, std::placeholders::_1), nullptr, nullptr);

        // 然后需要构建已经就绪的事件的缓冲区
        _revs = new struct epoll_event[_revs_num];
    }
    void Accepter(Conncet *conn)
    {
        // logMessage(DEBUG, "Accepter被调用\n");
        // 当accepter被调用后，说明有新的连接到来了，该函数要做的就是将新的连接添加到epoll模型中，将新的连接添加到unorder_map中
        while (1)
        {
            string ip;
            uint16_t port;
            int errorflag = 0;
            int sock = Sock::Accept(conn->_sock, &ip, &port, &errorflag);
            if (sock < 0)
            {
                if (errorflag == EWOULDBLOCK || errorflag == EAGAIN) // 说明只是底层没数据了 并不是错误了
                    break;
                else if (errorflag == EINTR)
                    continue;
                else // 走到这里才算真正的读取失败
                {
                    logMessage(ERROR, "accept error %d : %s\n", errorflag, strerror(errorflag));
                }
            }
            if (sock >= 0)
            {
                AddConnection(sock, std::bind(&TcpSever::Recver, this, std::placeholders::_1), std::bind(&TcpSever::Sender, this, std::placeholders::_1), std::bind(&TcpSever::Excepter, this, std::placeholders::_1));
                logMessage(DEBUG, "客户端连接成功,[%s] [%d]\n", ip.c_str(), port);
            }
        }
    }
    void LoopOnce()
    {
        int n = _epoll.WaitEpoll(_revs, _revs_num);
        for (int i = 0; i < n; i++)
        {
            int sock = _revs[i].data.fd;
            if (_revs[i].events & EPOLLIN) // 如果到来的事件是个读事件
            {
                if (IsConnectExist(sock) && _connects[sock]->_recv_cb)
                {
                    _connects[sock]->_recv_cb(_connects[sock]);
                }
            }
            if (_revs[i].events & EPOLLOUT)
            {
                if (IsConnectExist(sock) && _connects[sock]->_send_cb)
                {
                    _connects[sock]->_send_cb(_connects[sock]);
                }
            }
        }
    }
    void Dispather()
    {
        while (1)
        {
            LoopOnce();
        }
    }
    bool IsConnectExist(int sock)
    {
        auto f = _connects.find(sock);
        if (f == _connects.end())
            return false;
        else
            return true;
    }
    void EnableReadWrite(Conncet *conn, bool readeable, bool writeable)
    {
        uint32_t events = (readeable ? EPOLLIN : 0) | (writeable ? EPOLLOUT : 0);
        int n = _epoll.CtrlEpoll(conn->_sock, events);
    }
    void Recver(Conncet *conn)
    {
        bool err = false;
        while (1)
        {
            char buffer[1024];
            ssize_t s = recv(conn->_sock, buffer, sizeof(buffer) - 1, 0);
            if (s < 0) // 说明读取失败了
            {
                if (errno == EWOULDBLOCK || errno == EAGAIN) // 说明只是没有数据了 并不是失败了
                    break;
                else if (errno == EINTR)
                    continue;
                else
                {
                    logMessage(ERROR, "recv error %d : %s\n", errno, strerror(errno));
                    conn->_except_cb(conn);
                    err = true;
                    break;
                }
            }
            else if (s == 0) // 说明对端关闭了
            {
                logMessage(DEBUG, "client[%d] quit, server close [%d]\n", conn->_sock, conn->_sock);
                conn->_except_cb(conn);
                err = true;
                break;
            }
            else // 读取成功
            {
                buffer[s] = 0;
                conn->_inbuffer += buffer;  
            }
        }
        if (!err) // 走到这里说明绝对读完了
        {
            conn->_outbuffer = conn->_inbuffer;
            //cout << conn->_inbuffer << endl;
            conn->_inbuffer.clear();
            cout<<"接收缓冲区已清空"<<conn->_inbuffer<<endl;
            conn->_tsvr->EnableReadWrite(conn,true,true);
            cout<<"打开写"<<endl;
        }
    }
    void Sender(Conncet *conn)
    {
        while (1)
        {
            ssize_t s = send(conn->_sock, conn->_outbuffer.c_str(), conn->_outbuffer.size(), 0);
            if (s <= 0) // 发送失败了吗？不确定
            {
                if (errno == EWOULDBLOCK || errno == EAGAIN)
                    break;
                else if (errno == EINTR)
                    continue;
                else
                {
                    logMessage(ERROR, "send error %d : %s\n", errno, strerror(errno));
                    conn->_except_cb(conn);
                    break;
                }
            }
            // else if (s == 0) // 对端关闭了
            // {
            //     logMessage(ERROR, "服务器好像关闭了？生意不做了？\n");
            //     conn->_except_cb(conn);
            //     break;
            // }
            else // 发送成功
            {
                conn->_outbuffer.erase(0, s);
                if (conn->_outbuffer.empty())
                {
                    cout<<"发送缓冲区已空"<<endl;
                    break;
                }
            }
        }
        if (conn->_outbuffer.empty())
        {
            cout<<"关闭写"<<endl;
            cout<<conn->_inbuffer<<" "<<conn->_outbuffer<<endl;
            EnableReadWrite(conn, true, false);
        }
            
        else
        {
            cout<<"保持写打开"<<endl;
            EnableReadWrite(conn, true, true);
        }
            
    }
    void Excepter(Conncet *conn)
    {
        if (!IsConnectExist(conn->_sock))
            return;
        // 1. 从epoll中移除
        bool res = _epoll.DelFromEpoll(conn->_sock);
        assert(res); // 要判断
        // 2. 从我们的unorder_map中移除
        _connects.erase(conn->_sock);
        // 3. close(sock);
        close(conn->_sock);
        // 4. delete conn;
        delete conn;

        logMessage(DEBUG, "Excepter 回收完毕，所有的异常情况");
    }
    void AddConnection(int sock, func_t recv_cb, func_t send_cb, func_t except_cb)
    {
        Sock::SetNonBlock(sock);
        // 创建sock对象
        Conncet *conn = new Conncet(sock, this);
        conn->_recv_cb = recv_cb;
        conn->_send_cb = send_cb;
        conn->_except_cb = except_cb;
        // 将sock添加到epoll里面

        _epoll.AddSockToEpoll(sock, EPOLLIN | EPOLLET);
        // 将sock添加到unord_map里面
        _connects.insert({sock, conn});
    }
    ~TcpSever()
    {
        if (_listensocket > 0)
            close(_listensocket);
        if (_revs)
            delete[] _revs;
    }

private:
    int _listensocket;
    uint16_t _port;
    Epoll _epoll;
    struct epoll_event *_revs;
    int _revs_num;
    unordered_map<int, Conncet *> _connects;
    //_callback_t _cb;
};
